package edu.se.jai.lesson04guess2.service;

import edu.se.jai.lesson04guess2.model.MessageType;
import edu.se.jai.lesson04guess2.model.entity.GameRoom;
import edu.se.jai.lesson04guess2.model.entity.Player;
import edu.se.jai.lesson04guess2.model.message.ConnectData;
import edu.se.jai.lesson04guess2.model.message.GuessResult;
import edu.se.jai.lesson04guess2.model.message.Room;
import edu.se.jai.lesson04guess2.model.message.WebSocketMessage;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

/**
 * 消息发送服务
 * 
 * 负责发送各种WebSocket消息，包括：
 * - 点对点消息：发送给特定用户
 * - 房间广播消息：发送给房间内所有玩家
 * - 全局广播消息：发送给所有在线用户
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class MessageSend {

	private final SimpMessagingTemplate messagingTemplate;
	private final GameService gameService;
	
	/**
	 * 将GameRoom转换为Room消息对象
	 * 
	 * @param gameRoom 游戏房间对象
	 * @return 房间消息对象
	 */
	private Room convertGameRoomToRoom(GameRoom gameRoom) {
		Room room = new Room();
		BeanUtils.copyProperties(gameRoom, room);
		
		// 设置创建者名称
		if (gameRoom.getCreatorSessionId() != null) {
			Player creator = gameService.getPlayerBySessionId(gameRoom.getCreatorSessionId());
			if (creator != null) {
				room.setCreatorName(creator.getName());
			}
		}
		
		// 确保players字段正确复制
		room.setPlayers(gameRoom.getPlayers());
		
		return room;
	}
	
	/**
	 * 通知房间被解散
	 * 
	 * @param room 被解散的房间
	 */
	public void notifyRoomDissolved(GameRoom room) {
		WebSocketMessage message = new WebSocketMessage();
		message.setType(MessageType.ROOM_DISSOLVE);

		Room roomMessage = convertGameRoomToRoom(room);
		message.setData(roomMessage);

		// 广播给所有订阅了房间列表的玩家
		messagingTemplate.convertAndSend("/topic/roomUpdate", message);
		log.info("已广播房间解散通知: {}", roomMessage.getRoomId());
	}

	/**
	 * 通知房间更新
	 * 
	 * @param room 更新的房间
	 */
	public void notifyRoomUpdate(GameRoom room) {
		WebSocketMessage message = new WebSocketMessage();
		message.setType(MessageType.ROOM_UPDATE);

		Room roomMessage = convertGameRoomToRoom(room);
		message.setData(roomMessage);

		// 发送给房间内所有玩家
		messagingTemplate.convertAndSend("/room/" + roomMessage.getRoomId(), message);
		log.info("已通知房间 {} 更新，当前房间人数: {}", roomMessage.getRoomId(), room.getPlayers().size());

		// 广播房间更新给所有玩家
		messagingTemplate.convertAndSend("/topic/roomUpdate", message);
		log.info("已广播房间 {} 更新通知，当前房间人数: {}", roomMessage.getRoomId(), room.getPlayers().size());
	}


	/**
	 * 通知连接消息
	 * 
	 * @param playerName 玩家名称
	 * @param sessionId 会话ID
	 * @param success 连接是否成功
	 * @param info 连接信息
	 */
	public void notifyConnect(String playerName, String sessionId, boolean success, String info) {
		WebSocketMessage message = new WebSocketMessage();
		message.setType(MessageType.CONNECT_RESPONSE);

		ConnectData responseData = new ConnectData(playerName, sessionId, success, info);
		message.setData(responseData);
		log.info("玩家 {} 连接，{}", playerName, success);

		// 发送响应给指定用户
		messagingTemplate.convertAndSend("/queue/response-user" + sessionId, message);
	}

	/**
	 * 通知房间加入消息
	 * 
	 * @param room 房间对象
	 * @param sessionId 加入者的会话ID
	 */
	public void notifyJoin(GameRoom room, String sessionId) {
		WebSocketMessage message = new WebSocketMessage();
		message.setType(MessageType.ROOM_JOIN);

		Room roomMessage = convertGameRoomToRoom(room);

		message.setData(roomMessage);
		
		log.info("玩家 {} 加入房间 {}，当前房间人数: {}", sessionId, room.getRoomId(), room.getPlayers().size());
		
		// 发送给加入的玩家自己
		String userDestination = "/queue/response-user" + sessionId;
		messagingTemplate.convertAndSend(userDestination, message);
		
		// 发送给房间内其他玩家
		messagingTemplate.convertAndSend("/room/" + room.getRoomId(), message);
	}

	/**
	 * 通知房间离开消息
	 * 
	 * @param room 房间对象
	 * @param sessionId 离开者的会话ID
	 */
	public void notifyLeave(GameRoom room, String sessionId) {
		WebSocketMessage message = new WebSocketMessage();
		message.setType(MessageType.ROOM_LEAVE);

		Room roomMessage = convertGameRoomToRoom(room);
		message.setData(roomMessage);
		
		log.info("玩家 {} 离开房间 {}，当前房间人数: {}", sessionId, room.getRoomId(), room.getPlayers().size());
		
		// 发送给房间内其他玩家
		messagingTemplate.convertAndSend("/room/" + room.getRoomId(), message);
	}

	/**
	 * 通知房间创建消息
	 * 
	 * @param room 创建的房间
	 * @param sessionId 创建者的会话ID
	 */
	public void notifyCreate(GameRoom room, String sessionId) {
		WebSocketMessage message = new WebSocketMessage();
		message.setType(MessageType.ROOM_CREATE);

		Room roomMessage = convertGameRoomToRoom(room);
		message.setData(roomMessage);

		// 发送给创建者
		String userDestination = "/queue/response-user" + sessionId;
		messagingTemplate.convertAndSend(userDestination, message);
		log.info("发送创建房间响应: sessionId={}, roomId={}", sessionId, room.getRoomId());

		// 创建房间也是房间更新，广播给所有玩家
		notifyRoomUpdate(room);
	}
	/**
	 * 发送错误消息给指定用户
	 * 
	 * @param sessionId 目标用户的会话ID
	 * @param errorMessage 错误消息
	 */
	public void notifyErrorMessage(String sessionId, String errorMessage) {
		WebSocketMessage response = new WebSocketMessage();
		response.setType(MessageType.ERROR);
		response.setData(errorMessage);
		log.info("发送ERROR响应: sessionId={}, content={}", sessionId, errorMessage);
		
		String userDestination = "/queue/response-user" + sessionId;
		messagingTemplate.convertAndSend(userDestination, response);
		log.info("已发送ERROR响应到用户: {}", sessionId);
	}

	/**
	 * 发送所有房间列表
	 * 
	 * @param rooms 房间列表
	 * @param sessionId 目标用户的会话ID
	 */
	public void notifyAllRooms(List<GameRoom> rooms, String sessionId) {
		WebSocketMessage response = new WebSocketMessage();
		response.setType(MessageType.ROOMS_LIST);
		
		List<Room> roomList = new ArrayList<>();
		for (GameRoom room : rooms) {
			Room roomMessage = convertGameRoomToRoom(room);
			roomList.add(roomMessage);
		}
		
		response.setData(roomList);
		log.info("发送ALL_ROOMS_LIST响应: sessionId={}, {} 个房间", sessionId, roomList.size());
		
		String userDestination = "/queue/response-user" + sessionId;
		messagingTemplate.convertAndSend(userDestination, response);
		log.info("已发送ALL_ROOMS_LIST响应到用户: {}", sessionId);
	}

	// ==================== 游戏相关消息发送方法 ====================

	/**
	 * 通知游戏开始
	 * 
	 * @param room 房间对象
	 */
	public void notifyGameStart(GameRoom room) {
		WebSocketMessage message = new WebSocketMessage();
		message.setType(MessageType.GAME_START);

		Room roomMessage = convertGameRoomToRoom(room);
		message.setData(roomMessage);

		// 发送给房间内所有玩家
		messagingTemplate.convertAndSend("/room/" + room.getRoomId(), message);
		log.info("已通知房间 {} 游戏开始", room.getRoomId());

		// 广播房间更新给所有玩家
		notifyRoomUpdate(room);
	}

	/**
	 * 通知游戏停止
	 * 
	 * @param room 房间对象
	 */
	public void notifyGameStop(GameRoom room) {
		WebSocketMessage message = new WebSocketMessage();
		message.setType(MessageType.GAME_STOP);

		Room roomMessage = convertGameRoomToRoom(room);
		message.setData(roomMessage);

		// 发送给房间内所有玩家
		messagingTemplate.convertAndSend("/room/" + room.getRoomId(), message);
		log.info("已通知房间 {} 游戏停止", room.getRoomId());

		// 广播房间更新给所有玩家
		notifyRoomUpdate(room);
	}

	/**
	 * 通知猜测结果
	 * 
	 * 发送两种类型的GUESS_RESULT消息：
	 * 1. 个人反馈：发送给猜测者自己，包含详细提示和UI状态更新
	 * 2. 公开信息：发送给房间内其他玩家，显示公开的猜测信息
	 * 
	 * @param roomId 房间ID
	 * @param playerName 玩家名称
	 * @param guess 猜测数字
	 * @param result 猜测结果（true=正确，false=错误）
	 * @param hint 提示信息
	 * @param sessionId 猜测者的会话ID
	 */
	public void notifyGuessResult(String roomId, String playerName, Integer guess, Boolean result, String hint, String sessionId) {

		// 1. 发送个人反馈给猜测者
		//    - 创建GuessResult.createPersonalResult()对象
		//    - 设置消息类型为GUESS_RESULT
		//    - 发送到个人消息队列：/queue/response-user{sessionId}

		// 2. 发送公开信息给房间内其他玩家
		//    - 创建GuessResult.createPublicResult()对象
		//    - 设置消息类型为GUESS_RESULT
		//    - 发送到房间消息队列：/room/{roomId}


		//log.info("已通知房间 {} 猜测结果: 玩家 {} 猜测 {}，结果: {}", roomId, playerName, guess, result);
	}


}
